#ifndef DEVMGR_H_
#define DEVMGR_H_

#include <types.h>

#define DEV_TYPE_CPU 0x0
#define DEV_TYPE_IOAPIC 0x1
#define DEV_TYPE_PCI 0x2
#define DEV_TYPE_ISA 0x3
#define DEV_TYPE_LEGACY 0x4
#define DEV_TYPE_BUS 0x5

// copy pci spec device class codes for simplicity
#define DEV_CLASS_UKNOWN 0x0
#define DEV_CLASS_STORAGE 0x1
#define DEV_CLASS_NETWORK 0x2
#define DEV_CLASS_DISPLAY 0x3
#define DEV_CLASS_MULTIMEDIA 0x4
#define DEV_CLASS_MEMORYCTRL 0x5
#define DEV_CLASS_BRIDGE 0x6
#define DEV_CLASS_COMM 0x7
#define DEV_CLASS_SYSPERIPHERAL 0x8
#define DEV_CLASS_INPUT 0x9
#define DEV_CLASS_DOCK 0xA
#define DEV_CLASS_CPU 0xB
#define DEV_CLASS_SERIALBUS 0xC
#define DEV_CLASS_WIRELESS 0xD
#define DEV_CLASS_INTELIO 0xE
#define DEV_CLASS_SATCOM 0xF
#define DEV_CLASS_CRYPT 0x10
#define DEV_CLASS_SIGNAL 0x11

#define DEV_ERR_BADGINT 1
#define DEV_ERR_BADLOCATOR 2
#define DEV_ERR_BADHANDLE 3
#define DEV_ERR_NOALLOC 4

typedef int(*f_driver_init)(void);
typedef int(*f_driver_start)(void);
typedef int(*f_driver_stop)(void);
typedef int(*f_driver_handler)(void);

/**
 * Device structure
 */
typedef struct device
{
	byte type;
	byte class;
	const char *id;
	dword handle;  // unique handle to a particular device
	void *locator;  // pointer to a locator structure based on type
	dword gint;  // global interrupt number
	f_driver_init init;
	f_driver_start start;
	f_driver_stop stop;
	f_driver_handler handler;
} device_t;

/**
 * Locator structure for CPU / Local APIC
 */
typedef struct cpu_locator
{
	dword id;
	void *mem;
} cpu_locator_t;

/**
 * Locator structure for I/O APICs
 */
typedef struct ioapic_locator
{
	void *mem;
} ioapic_locator_t;

/**
 * Locator structure for PCI devices
 */
typedef struct pci_locator
{
	byte bus;
	byte device;
	byte function;
} pci_locator_t;

/**
 * Locator structure for ISA devices
 */
typedef struct isa_locator
{
	// i/o ports?
} isa_locator_t;

/**
 * Locator structure for Legacy devices
 */
typedef struct legacy_locator
{
	dword * ports;
	dword count;
} legacy_locator_t;

/**
 * Locator structure for Buses
 */
typedef struct bus_locator
{
	byte id;
} bus_locator_t;

// enumerate devices cb func
typedef int(*f_device_enum)(device_t *dev, void **context);

int init_devmgr(void);
int devmgr_add_device(device_t *dev);
int devmgr_enumerate_devices(f_device_enum, void **context);
dword devmgr_create_handle(void);
device_t * devmgr_get_device(dword handle);

#endif /*DEVMGR_H_*/
